using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc; 

namespace CoolCode.Web.Mvc.UI.Grid
{
	/// <summary>
	/// Renders a grid as an HTML table.
	/// </summary>
	public class HtmlTableGridRenderer<T> : GridRenderer<T> where T: class 
	{
		private const string DefaultCssClass = "grid";

		public HtmlTableGridRenderer() {}

		public HtmlTableGridRenderer(ViewEngineCollection engines) : base(engines)
		{
			
		}

        protected override void RenderGridStart()
        {
            RenderText(string.Format("<div id=\"{0}\" class=\"{1}\" style=\"{2}\">", GridModel.Container, "bbit-grid",""));// "height:500px;"
        }

        protected override void RenderGridEnd(bool isEmpty)
        {
            RenderText("</div>");
        }

        protected override void RenderEmpty()
        {
            RenderHeadStart();
            RenderHeaderCellStart();
            RenderHeaderCellEnd();
            RenderHeadEnd();
            RenderBodyStart();
            RenderText("<tr class=\"empty-text\"><td>" + GridModel.EmptyText + "</td></tr>");
            RenderBodyEnd();
        }

        protected void RenderHeaderCellStart()
        {
            RenderText("<th>");
        }

		protected override void RenderHeaderCellStart(GridColumn<T> column)
        {
            //column.HeaderAttributes.AddIfNotExists("width", column.Width + "px");
            AddStyleIfNotExists(column.HeaderAttributes, "width", column.Width + "px");
            string attributeString = BuildHtmlAttributes(column.HeaderAttributes);
            attributeString = AddSpaceIfNotEmpty(attributeString);

            //RenderText(string.Format("<th{0}>", attributeString ));
            RenderText( "<th>" );
            RenderText(string.Format("<div{0}>", attributeString));
		}

		protected override void RenderHeaderCellEnd()
        {
            RenderText("</div>");
			RenderText("</th>");
		}

		protected override void RenderRowStart(GridRowViewData<T> rowData)
		{
			var attributes = GridModel.Sections.Row.Attributes(rowData);
            attributes.AddIfNotExists("class", () => { return rowData.IsAlternate ? "erow" : "row"; });
			 
			string attributeString = BuildHtmlAttributes(attributes);
            attributeString = AddSpaceIfNotEmpty(attributeString);

            RenderText(string.Format("<tr{0}>", attributeString));
		}

		protected override void RenderRowEnd()
		{
			RenderText("</tr>");
		}

		protected override void RenderStartCell(GridColumn<T> column, GridRowViewData<T> rowData)
		{
			var attributes =column.Attributes(rowData) ;
            //attributes.AddIfNotExists("width", column.Width + "px");
            AddStyleIfNotExists(attributes, "width", column.Width + "px");

            string attributeString = BuildHtmlAttributes(attributes);
            attributeString = AddSpaceIfNotEmpty(attributeString);

            //RenderText(string.Format("<td{0}>", attributeString));
            RenderText("<td>");
            RenderText(string.Format("<div{0}>", attributeString));
		}

        protected override void RenderEndCell()
        {
            RenderText("</div>");
            RenderText("</td>");
        }

		protected override void RenderHeadStart()
		{
            var attributes = GridModel.Sections.HeaderRow.Attributes(new GridRowViewData<T>(null, false));
            string attributeString = BuildHtmlAttributes(attributes);
            attributeString = AddSpaceIfNotEmpty(attributeString);

            RenderText("<div class=\"hDiv\">");
            RenderText("<div class=\"hDivBox\">");
            RenderText(string.Format("<table{0} cellpadding=\"0\" cellspacing=\"0\">", ""));
			RenderText(string.Format("<thead><tr{0}>", attributeString));
		}

		protected override void RenderHeadEnd()
		{
            RenderText("</tr></thead>");
            RenderText("</table>");
            RenderText("</div>");
            RenderText("</div>");
		}

		protected override void RenderBodyStart()
        { 
            //GridModel.Attributes.AddIfNotExists("class", DefaultCssClass);
            string attributeString = BuildHtmlAttributes(GridModel.Attributes );
            attributeString = AddSpaceIfNotEmpty(attributeString);

            RenderText("<div class=\"bDiv\">");
            RenderText(string.Format("<table{0} border=\"0\" cellpadding=\"0\" cellspacing=\"0\">", attributeString));
			RenderText("<tbody>");
		}

		protected override void RenderBodyEnd() 
		{
			RenderText("</tbody>");
            RenderText("</table>");
            RenderText("</div>");
		} 

		/// <summary>
		/// Converts the specified attributes dictionary of key-value pairs into a string of HTML attributes. 
		/// </summary>
		/// <returns></returns>
		private static string BuildHtmlAttributes(IDictionary<string, object> attributes)
		{
			if(attributes == null || attributes.Count == 0)
			{
				return string.Empty;
			}

			const string attributeFormat = "{0}=\"{1}\"";

			return string.Join(" ",
                   attributes.Select(pair => string.Format(attributeFormat, pair.Key, pair.Value)).ToArray()
			);
		}

        private static string AddSpaceIfNotEmpty(string value)
        {
            if (value.Length > 0)
            {
                return " " + value;
            }
            return value;
        }

        private static void AddStyleIfNotExists(IDictionary<string, object> attributes, string name, object value)
        {
            string newStyle=string.Format("{0}:{1};",name,value );
            if (!attributes.ContainsKey("style") || attributes["style"]==null)
            {
                attributes["style"] = newStyle;
            }
            else
            {
                string curStyle=attributes["style"].ToString();
                if (!curStyle.Contains("width"))
                    attributes["style"] = newStyle + curStyle ;
            }
        }
	}
}